[Back]

MacOS X Developer Preview 4 Release Notes Copyright © 2000 by Apple Computer, Inc. All Rights Reserved.

Mac OS X Developer Preview 4 Release Notes:
Java

This implementation of the Java virtual machine and class libraries is based on the Java Development Kit (JDK) version 1.2.2.

Please do not discuss OS X Java in public forums like the MRJ-Dev mailing list -- that would violate your NDA. If you are interested in signing up for the NDA MacOS X and Java listserver, please send email to bluker1@apple.com with a subject of "macxjava" and a message body consisting of your registered ADC email address and name on the first line.

CAUTION: In this release, MRJAppletLauncher runs applets with all security turned off. This allows applets to potentially access your local filesystem, system properties, and network. Use caution when using MRJAppletLauncher to run applets from unknown sources. For more details, see MRJAppletLauncher in Launching and Packaging below.


Java Virtual Machine

We have added the HotSpot virtual machine from the JDK 1.3 technology train, and established it as the default VM. To explicitly choose a VM from the command line, overriding the default, use one of these two options:

$ java -classic ... (to choose the Classic JDK 1.2 VM with Symantec JITC)

$ java -hotspot ... (to choose the HotSpot VM)

To change the default VM that is invoked when you just type "java ..." on the command line, do the following:

$ su root
$ cd /System/Library/Frameworks/JavaVM.framework/Libraries

and then run one of the following commands:

$ ln -s -f libclassic.B.dylib libjvm.dylib (to make the Classic JDK VM the default)

$ ln -s -f libhotspot.B.dylib libjvm.dylib (to make the HotSpot VM the default)

Note that some Classic VM options (e.g. JITC settings) are not applicable to the HotSpot VM, and vice versa. HotSpot VM options are in the "non-standard" group that are of the form -Xoptionname. Type java -X for a list of these options.

Also note that HotSpot performance is very good in real-world applications, but has not been tuned for micro-benchmarks such as CaffeineMark.

Java threads are native Mach threads and as such are fully preemptive, even (unlike earlier versions of MRJ) with regard to the host app and other applications.

Thread priorities aren't implemented yet. All threads run at the same priority and get/setThreadPriority have no effect. This will be fixed before GM.


Debugging

GDB

You can't type "gdb java" to debug your native code, because gdb won't recognize the script "/usr/bin/java" as an executable format. To debug using gdb you must type the full path to the java executable, like this:

$ gdb /System/Library/Frameworks/JavaVM.framework/Versions/1.2/Commands/java

Implementing "/usr/bin/java" as a script is a temporary workaround. It will be restored to a symbolic link in future releases.

Once gdb starts, you may establish a different CLASSPATH for loading java code from within gdb:

(gdb) setenv CLASSPATH foo:bar
(gdb) run nameofjavaclass arguments

JDB

In this release, JDB does not work with with the default HotSpot Java Virtual Machine. Please invoke JDB as follows to debug your Java code:

	$ jdb -tclassic nameofjavaclass arguments


AWT

The AWT implementation is a Carbonized version of the one in MRJ 2.2, extended to support Java2. It was last synchronized against the MRJ 2.2 sourcebase last summer, so many of the more recent changes and fixes in MRJ 2.2 are not yet included. We will soon be synchronizing with the final 2.2 sources.

In the DP3 release notes we wrote, "In general, our goal so far has been to get Java 1.1-style functionality up and running. We've chosen to get most features limping rather than polishing any of them too much". Since DP3 we've done a lot of work on improving stability and correctness of basic AWT functionality, as well as implementing a lot more of Java2D. There has been some performance work (including making redrawing smoother) but a lot remains to be done.

Notable improvements since DP3 include:

Known problems include:

Debugging features for AWT

In this build, pressing the F13 key will dump the active window's Component hierarchy to System.out (by calling the Window's list( ) method). Option-F13 will dump the ComponentPeer hierarchy, which is slightly different and contains interesting information about clip regions.

Pressing the F14 key will completely erase and repaint the active window. This is useful when investigating drawing problems, either in your code our ours. (Note that since windows are double-buffered, the traditional tricks like dragging the window content offscreen and back will not work; the same buffer contents will simply be redrawn again!)

(We apologize to those with USB keyboards that do not have these keys!)

Windows and Dialogs

Window grow-boxes always intrude. There's no way to change this behavior yet (a la the checkbox in JBindery or MRJAppBuilder).

Window layering is not yet correct. As in MRJ 2.2, "child windows" (instances of java.awt.Window) float in front of all Frames and Dialogs. Also, modal dialogs should probably be displayed as Aqua-style "sheets", but aren't yet.

Window resizing is now "live". This may be annoyingly slow in complex windows.

Window titles, as well as menu titles and menu items, can now use any Unicode characters supported by OS X. (In previous versions of MRJ, characters of different writing systems, i.e. Kanji and Arabic, couldn't be mixed in a single title.)

FileDialog works better than in DP3 but still has a lot of problems with event delivery. If a FileDialog won't redraw or respond to events, switching to another application and then back will usually unblock it.

Graphics

Graphics performance is significantly below that of MRJ 2.2 (although better than in DP3). We're using Quartz for all graphics -- as opposed to the JDK, which drops down to GDI or X for simple 1.1-style drawing -- and Quartz is very fast at complex rendering but not yet as fast as QuickDraw for basic shapes like lines. (Also, anti-aliasing is currently always on.) Graphics performance will be a major priority for the final release.

Windows in OS X are double-buffered. Deciding exactly when the buffer should be flushed to the screen has been tricky. Currently, after a Graphics object is disposed, we schedule a flush to occur after the current event (if any) finishes. This usually results in smooth redrawing without redundant blits.

There is also a timer that flushes all windows twice a second; this is a hack to handle a few apps (like CaffeineMark!) that run lengthy animations with a single Graphics object. We are considering removing this hack, as it's not needed in most cases and results in unnecessary drawing. In any case, if for some reason you need to force window buffers to be flushed immediately, just call Toolkit.sync( ).

Graphics clipping is now much more correct -- this makes a huge difference for heavyweight (non-Swing) components.

Java2D

Our Java2D implementation is primarily based on Apple's Quartz graphics engine. The two have very similar feature sets (inherited largely from PostScript). For complex graphics, our Java2D implementation has up to 5x the performance of Sun's implementation -- but see the note in the Graphics section, above, on reduced performance of simple 1.1-style graphics.

Since DP3, the major improvement has been in Java2D Text functionality, including GlyphVectors and Swing editable text fields. This includes shapes from glyphs.

Java2D's basic features work, including AffineTransforms, paths, and all the 2D shapes. However, some features are still missing or incomplete in this build:

We will not ever have pixel for pixel match with the Sun Java2D implementation, especially with anti-aliasing. Quartz's anti-aliasing algorithms for both line art and text are different than Sun's default implementations, so the rendered pixels will not match exactly. On the other hand, we think you will appreciate the added performance and quality of our Quartz graphics system over other platforms' Java2D implementations.

As the Java2D spec points out, it cannot be assumed that a particular raster or databuffer type exists for a particular type of image, unless the developer hand-creates one. This means that for Swing and other users of createCompatibleImage, developers may be surprised to find another raster and databuffer type underneath their image. This is according to spec, and by design, but will break some offending code, such as Java Advanced Imaging. There is ongoing work with Javasoft to fix this issue with their spec and with proper developer use of the Java2D API.

AWT Controls

[These notes refer to "peered" AWT components in the java.awt package, not to their Swing counterparts.]

java.awt.List components now work. They use a new implementation (which doesn't depend on the List Manager) that now supports horizontal scrolling.

Most of the cosmetic glitches with java.awt.ScrollPane components have been fixed, but they still mess up slightly in some situations.

java.awt.TextComponent components now work correctly, except that the selection is not displayed while you drag, only after you release the mouse button.

Aqua controls (notably pushbuttons) are now vertically resizable. Also, in DP4 their metrics were changed to more closely match those of the OS 8/9 "Platinum" theme, which means they're now somewhat smaller than in DP3.

Font metrics are not working correctly, which may cause problems with the sizes of Buttons and other controls.

Swing

Since Swing UIs are implemented in cross-platform Java code (which we have not changed) and drawn using the Graphics API, they are not affected by the AWT peer bugs describe above.

There is a new Mac OS look-and-feel which uses the Appearance Manager to do its rendering, thus making it fully Aquafied.

Since OS X windows are already double-buffered, we have turned off Swing's own double-buffering, to save memory and eliminate unnecessary blits. Our buffer-flush code isn't yet as mature as Swing's RepaintManager, so in DP4 redrawing may not yet be as smooth as in "normal" Swing.

Font metrics are not working correctly, which causes drawing and selection problems with Swing editable text.


Security

There is a bug that sometimes causes an installed SecurityManager to check operations performed by trusted code; this will cause spurious SecurityExceptions to be thrown for valid operations. To work around this, do not install any SecurityManagers. When using the appletviewer command, always use the -nosecurity option.


Sound

Sound isn't working at all yet (apart from Toolkit.beep). Sorry.


JDirect

Mac OS X implements JDirect3. JDirect2 code will require minor modifications to run under JDirect3. JDirect1, which has been deprecated since 1997, is no longer supported.

The JDirect sample code supplied in source form in the MRJ 2.2 SDK will not work on OS X. That code is not Carbonized and it does not use JDirect3.

We will post a TechNote on how to convert JDirect2 code to use JDirect3 on Mac OS X. The quick summary is that you will need to add a static Object field to each class that has JDirect native methods, and initialize it with a new com.apple.mrj.jdirect.Linker(Class). You will also need to add a static String named JDirect_MacOSX which is initialized to a full path to the dylib (mach-o dynamic library) containing the native methods. For example:

   // JDirect3 example for Mac OS X
   public class Prime {
                  
      // The call to new Linker() installs the native methods 
      public static Object linkage = new com.apple.mrj.jdirect.Linker(Prime.class);
      
      // This string tells JDirect where to find the native code
      public static final String JDirect_MacOSX = "prime.dylib";
                  
      public static native long ComputePrime(short n);
   }

Toolbox synchronization

It is now imperative that you synchronize all Toolbox calls against the Toolbox.LOCK as described in TechNote 1153. Java threads are native Mach threads and can preempt Toolbox calls made by the host app or by other Java threads. Carbon is not yet reentrant or thread-safe, and reentrant calls can corrupt memory or crash the app, so it's imperative that only one thread be inside Carbon at any time.

Debugging features for JDirect

To help debug JDirect on Mac OS X, if you define a shell variable named JDIRECT_VERBOSE, JDirect will write verbose loading info to stderr. For instance, in csh,

% setenv JDIRECT_VERBOSE

will set the shell variable. Note: This only works when launching java code from the command line. Future releases will allow the verbose mode to be set in MRJAppBuilder.

MethodClosureUPP not supported

The class MethodClosureUPP is not supported on Mac OS X. The design of that class assumes the existence of MixedMode. If you are using toolbox callbacks and want code that will run on Mac OS 9 or OS X, you will need to have a helper class that creates a new MethodClosureUPP when on Mac OS 9 or a new MethodClosure when on Mac OS X.


JManager and Embedding

Starting with DP4, we are transitioning to the new JManager3 API. The JManager2 API is deprecated and JManager1, which has been deprecated since 1997, has been removed.

You should not attempt to call the JManager2 APIs. These are present but non-functional in DP4. They will be removed before Mac OS X GM.

The JManager3 API is much smaller than JManager2. Most of the functionality of the JManager2 API is available through either the JNI Invocation API or the CoreFoundation API, or is unnecessary and has been removed. The functions remaining in the JManager3 API are primarily applet embedding and utility functions.

Applications that want to invoke Java should launch a Java VM using the standard JNI Invocation API. Unlike the "classic" Mac OS, Java code invoked this way can now use AWT. The AWT will simply open its own windows, and add its own menus to the menu-bar while its windows are active. It will receive events on its own thanks to the Carbon event model. All your app needs to do is recognize that these windows and menus don't belong to it and refrain from manipulating them itself. JManager3 provides utility functions to determine whether a window belongs to Java or not.

Only applications that want to embed a Java applet into their own native windows need to use the new JManager3 control creation APIs. These create a "Java Control" -- a standard Control Manager control that contains a Java applet. The JManager3 control creation APIs take a native WindowRef that references the window into which the Java Control is to be embedded.


Launching and Packaging

In this developer release, we have ported MRJAppBuilder so that you can now build Java applications to run on Mac OS X. JBindery is obsolete and will not be ported. We have also provided a new application, MRJAppletLauncher, for launching applets. MRJAppletLauncher is written entirely in Java and replaces the now obsolete Apple Applet Runner. Both MRJAppBuilder and MRJAppletLauncher are in very preliminary form and contain several known bugs. Be sure to read the Known Problems sections below.

MRJAppBuilder

MRJAppBuilder builds applications in the new Carbon application bundle format. Before launching MRJAppBuilder, you need to have already created a properties (configuration) file. At a minimum, your properties file must contain the name of the main class and the classpath as follows:

com.apple.mrj.application.main = MyMainClass
com.apple.mrj.application.classpath = ../MyJarFile.jar:../MoreClasses.jar

The above classpath specification identifies MyJarFile.jar as residing in the same directory as the application. For a complete list of properties you can set in MRJAppBuilder, please see the documentation in the MRJ 2.2 SDK (available only for Mac OS 9). In this release, you will have to manually enter the paths to the application and to the configuration file. Using the Navigation Services dialog to select a file doesn't work reliably in this release, and so the two "Select..." buttons and the "Add..." button have been disabled. In addition, drag and drop of files from the desktop to MRJAppBuilder doesn't work in this release. Because of these problems, you must enter fully qualified pathnames as follows:

Application: /mydisk/tests/myapp.app
Configuration file: /mydisk/tests/myconfigfile

Known problems:

MRJAppletLauncher

MRJAppletLauncher is a utility that allows you to launch Java applets. MRJAppletLauncher provides a user interface around Sun's sun.applet.AppletViewer class and provides more features than the appletviewer command-line tool from Sun, which is based on the same class. You can launch an applet from the Favorites menu, or you can enter the path to an applet using its fully-qualified URL, and then press the Launch button. For example, entering the following URL will launch the Sun Tumbling Duke example applet:

http://java.sun.com/applets/other/TumblingDuke/index.html

Known problems:

Launching from the command-line

JDK-style command-line launching from the Terminal app is fully supported (as are all your favorite JDK tools). You can still use "java" to launch apps and "appletviewer" to launch applets. (Invoking these with no arguments will print a brief help message.) The Terminal window serves as the Java console. You can kill a Java process by activating the Terminal window that launched it and pressing Ctrl-C.

Known problems:

4.8 t 20000503